using System;
using System.IO;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;

namespace OracleInternal.NotificationServices
{
	internal class ReceiverThread : SupportClass.ThreadClass
	{
		private ONS oems;

		private NodeList nodeList;

		private Connection connection;

		private object lock_Renamed;

		private bool shutdown_Renamed_Field;

		private ONSTcpClient s;

		private string id_Renamed_Field;

		private static sbyte[] connectmessage3;

		private static sbyte[] connectmessage;

		private static sbyte[] selfid;

		private static sbyte[] endconnect;

		protected internal ReceiverThread(NodeList list, Connection co)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.ctor);
			}
			lock_Renamed = new object();
			shutdown_Renamed_Field = false;
			base.IsBackground = true;
			nodeList = list;
			oems = list.ons;
			connection = co;
			s = null;
			connection.ClientReceiver = this;
			id_Renamed_Field = new StringBuilder("ReceiverThread[" + connection.Id + "]").ToString();
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.ctor);
			}
		}

		private bool establishConnection(bool first)
		{
			ONSTcpClient oNSTcpClient = null;
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.establishConnection);
			}
			try
			{
				try
				{
					oNSTcpClient = connection.connect();
				}
				catch (TimeoutException ex)
				{
					OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.establishConnection, ex);
					return true;
				}
				if (oNSTcpClient == null)
				{
					return false;
				}
				bool result = false;
				try
				{
					OutputBuffer outputBuffer = new OutputBuffer(oNSTcpClient.GetStream());
					if (connection.ServerVersion == 3)
					{
						outputBuffer.putBytes(connectmessage3, connectmessage3.Length);
					}
					else
					{
						outputBuffer.putBytes(connectmessage, connectmessage.Length);
					}
					outputBuffer.putBytes(selfid, selfid.Length);
					outputBuffer.putString(oems.oraclehome);
					outputBuffer.putBytes(endconnect, endconnect.Length);
					outputBuffer.flush();
					InputBuffer inputBuffer = new InputBuffer(new BufferedStream(oNSTcpClient.GetStream()));
					_ = inputBuffer.NextString;
					string nextString = inputBuffer.NextString;
					if (nextString[0] != 'V' || nextString[1] != 'e' || nextString[2] != 'r' || nextString[3] != 's' || nextString[4] != 'i' || nextString[5] != 'o' || nextString[6] != 'n')
					{
						oNSTcpClient.Close();
						return false;
					}
					int num;
					try
					{
						num = int.Parse(nextString.Substring(9, 1));
					}
					catch (FormatException ex2)
					{
						OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.establishConnection, ex2);
						oNSTcpClient.Close();
						return false;
					}
					if (num != connection.ServerVersion)
					{
						connection.ServerVersion = num;
						oNSTcpClient.Close();
						return false;
					}
					_ = inputBuffer.NextString;
					_ = inputBuffer.NextString;
					_ = inputBuffer.NextString;
					_ = inputBuffer.NextString;
					inputBuffer.skipBytes(Notification.clusteridheader.Length);
					oems.clusterid = inputBuffer.NextString;
					inputBuffer.skipBytes(Notification.clusternameheader.Length);
					oems.clustername = inputBuffer.NextString;
					inputBuffer.skipBytes(Notification.instanceidheader.Length);
					oems.instanceid = inputBuffer.NextString;
					inputBuffer.skipBytes(Notification.instancenameheader.Length);
					oems.instancename = inputBuffer.NextString;
					_ = inputBuffer.NextString;
				}
				catch (TimeoutException ex3)
				{
					OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.establishConnection, ex3);
					try
					{
						oNSTcpClient.Close();
					}
					catch (IOException ex4)
					{
						OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.establishConnection, ex4);
					}
					oNSTcpClient = null;
					result = true;
				}
				catch (IOException ex5)
				{
					OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.establishConnection, ex5);
					try
					{
						oNSTcpClient.Close();
					}
					catch (IOException ex6)
					{
						OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.establishConnection, ex6);
					}
					oNSTcpClient = null;
				}
				if (oNSTcpClient != null)
				{
					if (!oems.localConn)
					{
						connection.sender.flushSenderQueue();
					}
					connection.sender.quiescent(status: false);
					connection.setClientSocket(oNSTcpClient);
					connection.sender.wakeThread();
					s = oNSTcpClient;
					if (!first || !oems.localConn)
					{
						oems.resendSubscriptions(connection.sender);
						return result;
					}
					return result;
				}
				return result;
			}
			catch (Exception ex7)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.establishConnection, ex7);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.establishConnection);
				}
			}
		}

		public override void Run()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.Run);
			}
			SubscriptionNotification subscriptionNotification = null;
			InputBuffer inputBuffer = null;
			bool flag = false;
			bool first = true;
			bool flag2 = true;
			string text = null;
			try
			{
				if (!oems.localConn && oems.remoteIOtimeout != 0)
				{
					subscriptionNotification = new SubscriptionNotification(99, "(", w: false);
				}
				while (!shutdown_Renamed_Field && !connection.shutdown)
				{
					if (s != null)
					{
						try
						{
							inputBuffer = new InputBuffer(s.GetStream());
						}
						catch (Exception ex)
						{
							OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.Run, ex);
							return;
						}
					}
					while (!shutdown_Renamed_Field && s != null)
					{
						try
						{
							text = inputBuffer.NextString;
							if (flag)
							{
								flag = false;
							}
							if (text == null || text[0] != 'P' || text[1] != 'O' || text[2] != 'S' || text[3] != 'T' || text[4] != ' ')
							{
								continue;
							}
							goto IL_0227;
						}
						catch (TimeoutException ex2)
						{
							if (flag || subscriptionNotification == null)
							{
								OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.Run, ex2);
								s = null;
								text = null;
								connection.closeClientSocket();
							}
							else
							{
								flag = true;
								text = null;
								connection.sender.send(subscriptionNotification);
							}
							goto IL_0227;
						}
						catch (IOException ex3)
						{
							bool flag3 = false;
							if (ConnectionTimeoutError(ex3.InnerException))
							{
								if (flag || subscriptionNotification == null)
								{
									flag3 = true;
								}
								else
								{
									flag = true;
									text = null;
									connection.sender.send(subscriptionNotification);
								}
							}
							else
							{
								if (ex3.InnerException != null && ProviderConfig.m_bTraceLevelPrivate)
								{
									Trace.Write(OracleTraceLevel.Private, OracleTraceTag.ONS, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.Run, " InnerException: " + ex3.InnerException!.ToString() + "\n");
								}
								flag3 = true;
							}
							if (flag3)
							{
								if (ProviderConfig.m_bTraceLevelPrivate)
								{
									Trace.Write(OracleTraceLevel.Private, OracleTraceTag.ONS, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.Run, " Error Encountered, Closing Client Socket");
								}
								OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.Run, ex3);
								try
								{
									s = null;
									text = null;
									connection.closeClientSocket();
								}
								catch
								{
								}
							}
							goto IL_0227;
						}
						IL_0227:
						if (text == null)
						{
							continue;
						}
						if (text[6] == 'e' && text[7] == 'v' && text[8] == 'e' && text[9] == 'n' && text[10] == 't')
						{
							Notification notification = readNotificationMessage(inputBuffer);
							if (notification != null)
							{
								nodeList.deliver(notification);
								continue;
							}
							s = null;
							connection.closeClientSocket();
						}
						else if (text[6] == 's' && text[7] == 't' && text[8] == 'a' && text[9] == 't' && text[10] == 'u' && text[11] == 's')
						{
							if (!readStatusMessage(inputBuffer))
							{
								s = null;
							}
						}
						else
						{
							if (text[6] != 'q' || text[7] != 'u' || text[8] != 'i' || text[9] != 'e' || text[10] != 's' || text[11] != 'c')
							{
								continue;
							}
							while (text != null)
							{
								try
								{
									text = inputBuffer.NextString;
								}
								catch (IOException)
								{
									s = null;
									text = null;
									connection.closeClientSocket();
								}
							}
							connection.sender.quiescent(status: true);
						}
					}
					flag = false;
					int num = 0;
					long num2 = 0L;
					long num3 = 500L;
					int num4 = 180000;
					int num5 = 20;
					while (s == null && !shutdown_Renamed_Field)
					{
						if (establishConnection(first))
						{
							num2 = 5000L;
							connection.ScanDelay = 0L;
						}
						else if (num3 == 500 && connection.ServerVersion == 3)
						{
							num3 = 0L;
							continue;
						}
						if (s == null)
						{
							num++;
							if (num >= num5)
							{
								if (ProviderConfig.m_bTraceLevelPrivate)
								{
									Trace.Write(OracleTraceLevel.Private, OracleTraceTag.ONS, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.Run, "Exhausted ONS Connection retries without success.");
								}
								return;
							}
							if (connection.scanDelay != 0L)
							{
								num3 = connection.scanDelay;
								connection.ScanDelay = 0L;
							}
							else if (num2 >= 5000 || flag2)
							{
								num2 = 0L;
								nodeList.checkConnections(connection);
								if (shutdown_Renamed_Field)
								{
									break;
								}
							}
							num2 += num3;
							if (num > 30 && num3 < 5000)
							{
								num3 += 1000;
							}
							lock (lock_Renamed)
							{
								try
								{
									Monitor.Wait(lock_Renamed, TimeSpan.FromMilliseconds(num4));
								}
								catch (Exception ex5)
								{
									OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.Run, ex5);
								}
							}
						}
						else
						{
							nodeList.establishedConnection(connection);
							first = false;
						}
						flag2 = false;
					}
				}
			}
			catch (Exception ex6)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.Run, ex6);
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.Run);
				}
			}
		}

		internal bool ConnectionTimeoutError(Exception ex)
		{
			bool result = false;
			if (ex != null && ex is SocketException && ((RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && ((SocketException)ex).ErrorCode == 10060) || (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((SocketException)ex).ErrorCode == 110) || (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((SocketException)ex).ErrorCode == 60)))
			{
				result = true;
			}
			return result;
		}

		protected internal virtual void shutdown()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.shutdown);
			}
			try
			{
				shutdown_Renamed_Field = true;
				connection.closeClientSocket();
				lock (lock_Renamed)
				{
					try
					{
						Monitor.Pulse(lock_Renamed);
					}
					catch (Exception ex)
					{
						OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.shutdown, ex);
					}
				}
			}
			catch (Exception ex2)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.shutdown, ex2);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.shutdown);
				}
			}
		}

		private bool readStatusMessage(InputBuffer ibuf)
		{
			bool flag = true;
			int num = -1;
			bool success = false;
			string message = null;
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.readStatusMessage);
			}
			try
			{
				try
				{
					for (string nextString = ibuf.NextString; nextString != null; nextString = ibuf.NextString)
					{
						int num2 = nextString.IndexOf(':');
						if (num2 != -1)
						{
							string a = nextString.Substring(0, num2);
							string text = nextString.Substring(num2 + 2);
							if (string.Equals(a, "result", StringComparison.InvariantCultureIgnoreCase))
							{
								success = (string.Equals(text, "success", StringComparison.InvariantCultureIgnoreCase) ? true : false);
							}
							else if (string.Equals(a, "subscriberid", StringComparison.InvariantCultureIgnoreCase))
							{
								try
								{
									num = int.Parse(text);
								}
								catch (FormatException ex)
								{
									OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.readStatusMessage, ex);
									num = -1;
								}
							}
							else if (string.Equals(a, "message", StringComparison.InvariantCultureIgnoreCase))
							{
								message = text;
							}
						}
					}
				}
				catch (IOException ex2)
				{
					OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.readStatusMessage, ex2);
					flag = false;
				}
				if (num == -1)
				{
					flag = false;
				}
				if (flag)
				{
					if (num != 99)
					{
						oems.handleSubscriptionReply(num, success, message);
						return flag;
					}
					return flag;
				}
				return flag;
			}
			catch (Exception ex3)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.readStatusMessage, ex3);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.readStatusMessage);
				}
			}
		}

		private Notification readNotificationMessage(InputBuffer ibuf)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.readNotificationMessage);
			}
			try
			{
				return new Notification(ibuf, oems);
			}
			catch (IOException ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.readNotificationMessage, ex);
				return null;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.readNotificationMessage);
				}
			}
		}

		static ReceiverThread()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.cctor);
			}
			try
			{
				connectmessage3 = SupportClass.ToSByteArray(SupportClass.ToByteArray(new StringBuilder("POST /connect HTTP/1.1\r\nVersion: 3\r\nFormFactor: ").ToString()));
				connectmessage = SupportClass.ToSByteArray(SupportClass.ToByteArray(new StringBuilder("POST /connect HTTP/1.1\r\nVersion: 4\r\nFormFactor: ").ToString()));
				selfid = SupportClass.ToSByteArray(SupportClass.ToByteArray(new StringBuilder("\r\nSelfId: java; Home=").ToString()));
				endconnect = SupportClass.ToSByteArray(SupportClass.ToByteArray(new StringBuilder("\r\n\r\n").ToString()));
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.ctor, ex);
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.ReceiverThread, OracleTraceFuncName.cctor);
				}
			}
		}
	}
}
